package api

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"os"
	"path/filepath"
	"seat-service/initialization"
	"seat-service/model"
	"seat-service/model/dto"
	"seat-service/response"
	service "seat-service/service/impl"
	"strconv"
	"time"
)

type MessageApi struct {
}

var messageService service.MessageService

// UploadImg 上传图片
func (m *MessageApi) UploadImg(context *gin.Context) {
	//接收请求参数
	var uploadImgMessage dto.MessageImg
	if err := context.ShouldBind(&uploadImgMessage); err != nil {
		initialization.SeatLogger.Error("context.ShouldBindJSON(&uploadImgMessage) is failed", zap.Error(err))
		resp.Fail(context, response.CodeParamError, nil)
		return
	}
	//先删除旧的图片
	if uploadImgMessage.OldImgName != "" {
		// 转换路径分隔符为正斜杠
		oldImagePath := filepath.ToSlash(uploadImgMessage.OldImgName)
		err := os.Remove(oldImagePath)
		if err != nil {
			initialization.SeatLogger.Error("os.Remove(uploadImgMessage.OlgImgName) is failed", zap.Error(err))
			resp.Fail(context, response.UploadFileFail, nil)
			return
		}
	}
	// 获取当前日期
	currentTime := time.Now()
	dateFolder := currentTime.Format("2006-01-02")
	// 获取可执行文件所在的目录
	executablePath, _ := os.Executable()
	executableDir := filepath.Dir(executablePath)
	// 创建按日期分类的文件夹，父文件夹 uploads
	targetFolderPath := filepath.Join(executableDir, "uploads", "messageImg", dateFolder)
	// 递归创建目录，默认权限
	if err := os.MkdirAll(targetFolderPath, os.ModePerm); err != nil {
		initialization.SeatLogger.Error("os.MkdirAll(targetPath, os.ModePerm) is failed", zap.Error(err))
		resp.Fail(context, response.UploadFileFail, nil)
		return
	}
	// 将图片保存到文件夹中
	imageFile := uploadImgMessage.HeadImg
	// 获取上传文件的原始文件名
	originalFileName := uploadImgMessage.HeadImg.Filename
	// 提取文件后缀
	fileExt := filepath.Ext(originalFileName)
	// 生成保存的文件路径，加上文件后缀
	targetPath := filepath.Join(targetFolderPath, initialization.GenUUID()+fileExt)
	fmt.Println(targetPath)
	// 保存上传的文件到目标路径
	if err := context.SaveUploadedFile(imageFile, targetPath); err != nil {
		initialization.SeatLogger.Error("context.SaveUploadedFile(imageFile, targetPath) is failed", zap.Error(err))
		resp.Fail(context, response.UploadFileFail, nil)
		return
	}
	// 构建相对路径
	relativePath, err := filepath.Rel(targetFolderPath, targetPath)
	if err != nil {
		initialization.SeatLogger.Error("Error calculating relative path", zap.Error(err))
		resp.Fail(context, response.UploadFileFail, nil)
		return
	}
	// 将路径分隔符转换为正斜杠
	relativePath = filepath.ToSlash(relativePath)
	relativePath = "uploads/messageImg/" + dateFolder + "/" + relativePath
	resp.Success(context, response.CodeSuccess, relativePath)
}

// CreateAnnouncement 管理员创建通告
func (m *MessageApi) CreateAnnouncement(context *gin.Context) {
	var announcement dto.Announcement
	if err := context.ShouldBindJSON(&announcement); err != nil {
		initialization.SeatLogger.Error("context.ShouldBind(&announcement) is failed", zap.Error(err))
		resp.Fail(context, response.CodeParamError, nil)
		return
	}
	var announcemnetInformation model.Message
	announcemnetInformation.HeadImg = announcement.HeadImgUrl //图片路径
	announcemnetInformation.Content = announcement.Content
	announcemnetInformation.Status = announcement.Status
	announcemnetInformation.Type = announcement.Type //类型 , 用户须知 , 通告消息
	announcemnetInformation.Title = announcement.Title
	if err := messageService.CreateAnnouncement(announcemnetInformation); err != nil {
		initialization.SeatLogger.Error("messageService.CreateAnnouncement(announcemnetInformation) is failed", zap.Error(err))
		resp.Fail(context, response.CodeServerBusy, nil)
		return
	}
	resp.Success(context, response.CodeSuccess, nil)
}

// QueryAnnouncement 管理员查询通告
func (m *MessageApi) QueryAnnouncement(context *gin.Context) {
	//接收请求参数
	var p dto.PageParam
	if err := context.ShouldBindJSON(&p); err != nil {
		initialization.SeatLogger.Error("context.ShouldBindJSON(&dto.PageParam) is failed", zap.Error(err))
		resp.Fail(context, response.CodeParamError, nil)
		return
	}
	total, announcementInformations, err := messageService.QueryAnnouncement(p)

	if err != nil {
		initialization.SeatLogger.Error("messageService.QueryAnnouncement(p) is failed", zap.Error(err))
		resp.Fail(context, response.CodeServerBusy, nil)
		return
	}
	var responseData struct {
		Message []model.Message `json:"message"`
		Total   int64           `json:"total"`
	}
	responseData.Message = announcementInformations
	responseData.Total = total
	resp.Success(context, response.CodeSuccess, responseData)
}

// QueryAnnouncementById 根据id查询公告
func (m *MessageApi) QueryAnnouncementById(context *gin.Context) {
	//接收公告id
	messageIdStr := context.Query("id")
	messageId, err := strconv.Atoi(messageIdStr)
	if err != nil {
		initialization.SeatLogger.Error("strconv.Atoi(messageIdStr) is failed", zap.Error(err))
		return
	}
	announcementInformation, err := messageService.QueryAnnouncementById(messageId)
	if err != nil {
		initialization.SeatLogger.Error("messageService.QueryAnnouncementById(messageId) is failed")
		resp.Fail(context, response.CodeServerBusy, nil)
		return
	}
	resp.Success(context, response.CodeSuccess, announcementInformation)
}

// ChangeAnnouncement 管理员修改公告内容
func (m *MessageApi) ChangeAnnouncement(context *gin.Context) {
	//接收修改的内容
	var newAnnouncement model.Message
	if err := context.ShouldBindJSON(&newAnnouncement); err != nil {
		initialization.SeatLogger.Error("context.ShouldBindJSON(&newAnnouncement) is failed", zap.Error(err))
		resp.Fail(context, response.CodeParamError, nil)
		return
	}
	if err := messageService.UpdateAnnouncement(newAnnouncement); err != nil {
		initialization.SeatLogger.Error("messageService.UpdateAnnouncement(newAnnouncement) is failed", zap.Error(err))
		resp.Fail(context, response.CodeServerBusy, nil)
		return
	}
	//修改完成之后 , 拿到新修改的内容
	newAnnouncement, err := messageService.QueryAnnouncementById(int(newAnnouncement.ID))
	if err != nil {
		initialization.SeatLogger.Error("messageService.QueryAnnouncementById(int(newAnnouncement.ID)) is failed", zap.Error(err))
		resp.Fail(context, response.CodeServerBusy, nil)
		return
	}
	resp.Success(context, response.CodeSuccess, newAnnouncement)
}

// DeleteAnnouncement 管理员删除通告 批量删除
func (m *MessageApi) DeleteAnnouncement(context *gin.Context) {
	//接收通告ids
	var announcemnetIds dto.DeleteAnnouncementIds
	if err := context.ShouldBindJSON(&announcemnetIds); err != nil {
		initialization.SeatLogger.Error("context.ShouldBindJSON(&announcemnetIds) is failed", zap.Error(err))
		resp.Fail(context, response.CodeParamError, nil)
		return
	}
	if err := messageService.DeleteAnnouncementByIds(announcemnetIds); err != nil {
		initialization.SeatLogger.Error("messageService.DeleteAnnouncementByIds(announcemnetIds) is failed", zap.Error(err))
		resp.Fail(context, response.CodeServerBusy, nil)
		return
	}
	resp.Success(context, response.CodeSuccess, nil)
}

// StudentGetAllMessage 学生得到所有信息 无分页
func (m *MessageApi) StudentGetAllMessage(context *gin.Context) {
	allMessage, err := messageService.SelectAllMessage()
	if err != nil {
		initialization.SeatLogger.Error("messageService.SelectAllMessage() is error", zap.Error(err))
		resp.Fail(context, response.CodeServerBusy, nil)
		return
	}
	resp.Success(context, response.CodeSuccess, allMessage)
}

// StudentUserMessage 用户须知
func (m *MessageApi) StudentUserMessage(context *gin.Context) {
	userMessage, err := messageService.SelectUserMessage()
	if err != nil {
		initialization.SeatLogger.Error("messageService.SelectAllMessage() is error", zap.Error(err))
		resp.Fail(context, response.CodeServerBusy, nil)
		return
	}
	resp.Success(context, response.CodeSuccess, userMessage)
}
